﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace UBCon.Controls
{
    public abstract class ProgressBarBase:Control
    {
        #region Constructors

        static ProgressBarBase() 
        {
            Type ownerType = typeof(ProgressBarBase);
            EllipticalProgressBar.DefaultStyleKeyProperty.OverrideMetadata(ownerType, new FrameworkPropertyMetadata(ownerType));
        }

        public ProgressBarBase() 
        {
            Items = new ObservableCollection<Shape>();
            InitializeItems();
        }

        #endregion

        #region Properties

        public double ItemSize
        {
            get { return (double)GetValue(ItemSizeProperty); }
            set { SetValue(ItemSizeProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ItemSize.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ItemSizeProperty =
            DependencyProperty.Register("ItemSize", typeof(double), typeof(ProgressBarBase),
            new FrameworkPropertyMetadata(4.0D, new PropertyChangedCallback(OnItemSizePropertyChanged)));

        internal ObservableCollection<Shape> Items
        {
            get { return (ObservableCollection<Shape>)GetValue(ItemsProperty); }
            set { SetValue(ItemsProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Items.  This enables animation, styling, binding, etc...
        internal static readonly DependencyProperty ItemsProperty =
            DependencyProperty.Register("Items", typeof(ObservableCollection<Shape>), typeof(ProgressBarBase),
            new PropertyMetadata(null));

        public Brush Color
        {
            get { return (Brush)GetValue(ColorProperty); }
            set { SetValue(ColorProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Color.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ColorProperty =
            DependencyProperty.Register("Color", typeof(Brush), typeof(ProgressBarBase), new FrameworkPropertyMetadata(Brushes.Black));

        public double Distance
        {
            get { return (double)GetValue(DistanceProperty); }
            set { SetValue(DistanceProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Distance.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DistanceProperty =
            DependencyProperty.Register("Distance", typeof(double), typeof(ProgressBarBase), new FrameworkPropertyMetadata(6.0, new PropertyChangedCallback(OnDistancePropertyChanged)));

        public bool Finished
        {
            get { return (bool)GetValue(FinishedProperty); }
            set { SetValue(FinishedProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Finished.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty FinishedProperty =
            DependencyProperty.Register("Finished", typeof(bool), typeof(ProgressBarBase), new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnFinishedPropertyChanged)));

        #endregion

        #region Depenency Property Changed Callbacks

        private static void OnItemSizePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) 
        {
            ProgressBarBase pBase = sender as ProgressBarBase;
            pBase.OnItemSizeChanged(e);
        }

        private static void OnDistancePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) 
        {
            ProgressBarBase pBase = sender as ProgressBarBase;
            pBase.OnDistanceChanged(e);
        }

        private static void OnFinishedPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) 
        {
            ProgressBarBase pBase = sender as ProgressBarBase;
            pBase.OnFinishedChanged(e);
        }
        #endregion

        #region Overrides

        public virtual void OnItemSizeChanged(DependencyPropertyChangedEventArgs e) 
        {
            StartAnimation();
        }

        public virtual void OnDistanceChanged(DependencyPropertyChangedEventArgs e) 
        {
            StartAnimation();
        }

        public virtual void OnFinishedChanged(DependencyPropertyChangedEventArgs e) 
        {
            bool newValue = (bool)e.NewValue, oldValue = !newValue;
            if (newValue)
            {
                StopAnimation();
            }
            else
            {
                RestartAnimation();
            }
        }

        protected virtual void InitializeItems() { }
        #endregion

        #region Private Utilities

        protected virtual void BuildSimpleAnimation() { }

        protected void RestartAnimation()
        {
            if (SimplaAnimations.Count == 0)
            {
                BuildSimpleAnimation();
            }
            if (startTimer.IsEnabled)
            {
                startTimer.Stop();
            }

            startTimer.Start();
        }
        protected void StopAnimation()
        {
            if (SimplaAnimations.Count > 0)
            {
                for (int i = 0; i < ItemsCount; i++)
                {
                    SimplaAnimations[i].Stop();
                }
            }
            if (startTimer.IsEnabled)
            {
                startTimer.Stop();
            }
        }

        protected void StartAnimation()
        {
            if (startTimer.IsEnabled)
            {
                startTimer.Stop();
            }
            BuildSimpleAnimation();
            startTimer.Start();
        }

        #endregion

        #region Event Handlers
        #endregion

        #region Fields
        protected const string yPropertyPath = "(FrameworkElement.RenderTransform).(TranslateTransform.Y)";
        protected const string xPropertyPath = "(FrameworkElement.RenderTransform).(TranslateTransform.X)";
        protected const string opacityPath = "Opacity";
        protected Storyboard simpleAnimation;
        protected DispatcherTimer startTimer = new DispatcherTimer();
        protected Size infinteSize = new Size(double.PositiveInfinity, double.PositiveInfinity);
        protected int ItemsCount = 5;
        protected List<Storyboard> SimplaAnimations = new List<Storyboard>();
        #endregion

        #region Events
        #endregion
    }
}
